Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Генератор волн JX

Компоненты и расходные материалы

Arduino Nano R3
Я не пробовал, но, по-видимому, вы можете использовать любую модель Arduino
× 1
Отображение SH1106 I2C Oled 128x64 пикселей (4 контакта)
× 1
Модуль AD9833 DDS
× 1
Поворотный энкодер с кнопкой
Для этого вам понадобится паяльник
× 1
Модуль поворотного кодировщика
Для монтажа на макетной плате это лучше
× 1
Модуль реле 5 В (необязательно)
Необязательно, если нет необходимости изменять режим связи выхода переменного / постоянного тока. Для монтажа на макетной плате лучше
× 1
Релейный язычок 5 В 500 Ом
Это лучше всего подходит для слабого сигнала, но требует паяльника. С катушкой на 500 Ом можно. быть подключенным напрямую к цифровым выводам Arduino (10 мА).
× 1
Конденсатор 10 мкФ
× 1
Конденсатор 10 нФ
Полиэфирный конденсатор
× 1
AC-DC с 100–220 В до 5 В, понижающий источник питания модуль
Необязательно, для питания схемы без подключения через USB
× 1

Необходимые инструменты и машины

Паяльник (общий)
Это не обязательно, если вы хотите протестировать проект на макете

Приложения и онлайн-сервисы

image2cpp
Чтобы преобразовать пользовательские значки в шестнадцатеричный формат для PROGMEM

Об этом проекте

Долго откладывал покупку осциллографа. Теперь, после его покупки, пришло время приобрести недорогой генератор сигналов для хобби, необходимый для диагностики аудиосхем и многого другого. Объединяя две страсти к электронике и вычислениям, лучше всего сделать это самостоятельно с помощью Arduino.

ОСОБЕННОСТИ

  • Выходная частота от 1 Гц до 999999 Гц.
  • два режима изменения частоты:логарифмический и однозначный.
  • три типа волны:синус, треугольник и квадрат.
  • Выходное соединение переменного или постоянного тока.
  • возможность непрерывного переключения между двумя предопределенными значениями частоты.
  • управляется исключительно одной ручкой
  • встроенная заставка для продления срока службы OLED-дисплея.

ПРИМЕЧАНИЕ

ПРОТОТИП

Я использовал предварительно собранный релейный модуль с контактами на 10 А, потому что в тот момент у меня не было реле с микрогерконом, это был бы лучший выбор, чтобы избежать транзисторных диодов и резисторов, когда силовые реле не нужны. Цифровой PIN-код Arduino может выдавать максимум 40 мА, поэтому вы не можете напрямую подключить электромеханическое реле к катушке 120/150 Ом.

ВСЕГДА БУДЬТЕ ОЧЕНЬ ОСТОРОЖНЫ при питании от сети!

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

Код

  • JX_Wave_Generator_8.7.7.ino
  • JXWG_Defs.h
  • JXWG_Graphics.h
JX_Wave_Generator_8.7.7.ino C / C ++
Версия 8.7.7. Незначительная редакция от 16.01.2021
 / * Copyright (c) 2020 Janux Разрешение предоставляется бесплатно любому лицу, получающему копию этого программного обеспечения и связанных файлов документации («Программное обеспечение») для работы в Программном обеспечении без ограничений, включая, помимо прочего, права на использование, копирование, изменение, объединение, публикацию, распространение, сублицензирование и / или продажу копий Программного обеспечения, и разрешать лицам, которым предоставляется Программное обеспечение, делать это, при условии при соблюдении следующих условий:Приведенное выше уведомление об авторских правах и это уведомление о разрешении должны быть включены во все копии или существенные части Программного обеспечения. ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ, ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ И НЕЗАЩИТЫ ОТ ПРАКТИКИ. НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ АВТОРЫ ИЛИ ВЛАДЕЛЬЦЫ АВТОРСКИХ ПРАВ НЕ НЕСЕТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ПРЕТЕНЗИИ, УБЫТКИ ИЛИ ДРУГИЕ ОТВЕТСТВЕННОСТЬ, ПРОИЗВОДИМЫЕ В РЕЗУЛЬТАТЕ ДОГОВОРА, ПРАКТИКИ ИЛИ ИНЫМ ОБРАЗОМ, ВОЗНИКАЮЩИМ, ВНУТРЕННИЕ ИЛИ В СВЯЗИ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ ИЛИ ИСПОЛЬЗОВАНИЕМ ИЛИ ДРУГИМИ ДЕЛАМИ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ. Код сохранения-загрузки конфигурации является развитием оригинальной идеи статьи «Как загружать и сохранять конфигурации на Arduino» Рагнара Раньена Хомба на веб-сайте Norwegian Creation. * / # Include "JXWG_Defs.h" #include "JXWG_Graphics .h "void setup () {// если вы используете простой кодировщик и подтягивающие резисторы 3x10K, примените эти настройки ниже pinMode (PinA, INPUT); pinMode (PinB, ВХОД); pinMode (PinS, ВХОД); // если вы используете простой кодировщик без резисторов 3x10K, используйте следующую строку дерева // pinMode (PinA, INPUT_PULLUP); // pinMode (PinB, INPUT_PULLUP); // pinMode (PinS, INPUT_PULLUP); // БОЛЬШИНСТВО СВАРОЧНЫХ ЭНКОДЕРОВ УЖЕ ИМЕЕТ РЕЗИСТОРЫ НА ПИН А И В, НО НЕ НА ПИН ПЕРЕКЛЮЧАТЕЛЯ // затем используйте настройки ниже // pinMode (PinA, INPUT); // pinMode (PinB, INPUT); // pinMode (PinS, INPUT_PULLUP); digitalWrite (PinA, HIGH); digitalWrite (PinB, ВЫСОКИЙ); digitalWrite (PinS, HIGH); pinMode (PinCoupling, ВЫХОД); // Режим связи Encoder.setDebounceDelay (5); display.begin (SH1106_SWITCHCAPVCC, 0x3C); // инициализируем с адресом I2C 0x3C (для 128x64) display.clearDisplay (); //display.setRotation(2); // раскомментируйте эту строку, если хотите смонтировать дисплей вверх ногами Wire.begin (); // подключаемся к шине i2c как мастер TWBR =5; // freq =615kHz period =1.625uS // Назначает событие нажатия переключателя энкодера прерыванию 1 Pin 3 Arduino attachInterrupt (digitalPinToInterrupt (PinS), encoderSwitch, FALLING); DDS_Init (); // Инициализируем модуль DDS; setConfig (); // Загрузка конфигурации и установка значений запуска} // ---> end setup () void loop () {JX_WaveGenerator_MAIN ();} // ------------------- -------------------------------------------------- -------------------------------------------------- ------------------ // Функция JX WaveGenerator MAIN // ------------------------ -------------------------------------------------- -------------------------------------------------- ------------- void JX_WaveGenerator_MAIN () {byte encoderSpin =Encoder.rotate (); // Направление вращения энкодера 1 =CW, 2 =CCW byte encoderLongPush =Encoder.pushLong (1000); // событие длинного нажатия кодировщика long lStep =0; // текущее значение шага частоты long wTime =600000; // 10 мин if (encoderPush) delay (250); если (encoderSpin) {cTime =millis (); } else {если (millis () - cTime> wTime) {ScreenSaver (); }} переключатель (режим) {case LOGARITHMIC:// 0 // ----------------------------------- -------------------------------------------------- ---------------------------------------------- // режим ЛОГАРИФМИЧЕСКИЙ :Частота изменения вращения энкодера с логарифмическим шагом 1,10,100,1000,10000,100000 Гц // ------------------------------ -------------------------------------------------- -------------------------------------------------- - if (encoderSpin) {if (lFreq> =1) {lStep =AutoStep (lFreq, encoderSpin); // Вычислить логарифмический шаг} else if (_CouplingMode ==OFF) {// если режим связи выключен resetCouplingMode (); // установить режим связи по умолчанию, если частота не равна 0 encoderSpin =0; // пропускаем первое вращение} if (encoderSpin ==CW &&lFreq <=999999 - lStep) {// вращение CW увеличивает частоту lFreq + =lStep; } if (encoderSpin ==CCW &&lFreq> =lStep + 1) {// вращение против часовой стрелки уменьшает частоту lFreq - =lStep; } DDS_FrequencySet (lFreq, Wave [_WaveType]); // отправляем значение частоты в модуль DDS displayFrequency (lFreq); // отправляем отформатированную частоту для отображения lLastFreq =lFreq; // сохраняем текущую частоту} // ------------------------------------------ -------------------------------------------------- --------------------------------------- // рабочий режим ЛОГАРИФМИЧЕСКИЙ:переключатель энкодера в режим ОПЦИИ // ------------------------------------------------ -------------------------------------------------- --------------------------------- если (encoderPush) {encoderPush =false; // Очистить флаг push drawSymbol (1); // рисуем символ стрелки selectIcon (0, БЕЛЫЙ); // рисуем границу вокруг первого значка idx =0; idy =0; // сбросить указатели var mode =OPTIONS; // переходим в режим OPTIONS} break; // конечный режим LOGARITHMIC case SINGLEDIGIT:// 1 // ------------------------------------- -------------------------------------------------- ---------------------- // подрежим SINGLEDIGIT:вращение энкодера перемещает курсор влево и вправо // -------------- -------------------------------------------------- --------------------------------------------- if (encoderSpin) { если (encoderSpin ==CW &&idx  0) idx--; // указатель уменьшения против часовой стрелки // ------------------------------------------- -------------------------------------------------- --------------- // когда idx от 0 до 5 выбираем частоту цифр // --------------------- -------------------------------------------------- ------------------------------------- if (idx> =0 &&idx  =MAXDIGIT &&idx <=MAXDIGIT + 2) {// если текущая позиция за цифрами hideCursor (MAXDIGIT - 1); // скрываем курсор на последней цифре drawSymbol (1); // рисуем dn стрелку selectIcon (idx - MAXDIGIT, WHITE); // выберите значок}} // ------------------------------------------ -------------------------------------------------- --------------------------------------- // подрежим SINGLEDIGIT:событие нажатия кодировщика // - -------------------------------------------------- -------------------------------------------------- ------------------------------ if (encoderPush) {encoderPush =false; // ------------------------------------------------ -------------------------------------------------- ----------- // если выбраны цифры от 0 до 5 перейти в режим DIGITCHANGE // ---------------------- -------------------------------------------------- ------------------------------------- if (idx <=MAXDIGIT - 1) {hideCursor (idx ); // задержка мигания курсора (250); // для selectDigit (idx); // визуальное подтверждение drawSymbol (2); // рисовать значок поворота mode =DIGITCHANGE; // изменить режим} // ------------------------------------------- -------------------------------------------------- ---------------- // в противном случае будет выбран значок, затем перейдите в ОПЦИИ // -------------------- -------------------------------------------------- --------------------------------------- else {if (idx> =MAXDIGIT &&idx <=MAXDIGIT + 2) {idy =idx - MAXDIGIT; selectOption (idy); idy =варианты [idy]; } } } ломать; // конец режима SINGLEDIGIT case SWEEP:// 2 // ------------------------------------- -------------------------------------------------- ------------------------- // рабочий режим SWEEP:вращение энкодера перемещает курсор влево и вправо для выбора опции // -------- -------------------------------------------------- -------------------------------------------------- ---- если (encoderSpin) {если (encoderSpin ==CW &&idy <2) idy ++; если (encoderSpin ==CCW &&idy> 0) idy--; selectIcon (idy, БЕЛЫЙ); } if (encoderPush) {// ------------------------------------------ -------------------------------------------------- --------------------------------------- // рабочий режим SWEEP:нажатие кодировщика перейти к OPTIONS, ВАРИАНТЫ ПРОВЕРКИ или ПУСК / ОСТАНОВ // ----------------------------------------- -------------------------------------------------- ---------------------------------------- encoderPush =false; переключатель (idy) {case 0:lFreq =atol (Freq); selectOption (idy); idy =варианты [idy]; задержка (100); если (_WorkMode! =2) displayFrequency (lLastFreq); SweepReset (); ломать; случай 1:lFreq =atol (Freq); drawSymbol (9); drawSymbol (1); displaySweepIcons (); selectIcon (0, БЕЛЫЙ); idy =0; displayFrequency (_Sweep (idy)); задержка (100); SweepReset (); режим =OPTSWEEP; ломать; case 2:// ** sweepStatus:STILL 0 (никогда не запускался), 1 BREAK, 2 PAUSE ** if (sweepStatus ==STILL || sweepStatus ==PAUSE) {drawSymbol (3); // рисуем иконку паузы selectIcon (2, WHITE); // выбираем иконку FrequencySweep (); // запускаем развертку} else {// если приостановлено drawSymbol (4); // отрисовываем значок воспроизведения sweepStatus =PAUSE; } ломать; }} if (sweepStatus ==PAUSE) flashIcon (250); // мигающий текст паузы break; // конечный режим SWEEP case OPTIONS:// 3 if (encoderLongPush) reset (); // ------------------------------------------------ -------------------------------------------------- --------------------------------- // ОПЦИИ режима:параметр выбора вращения энкодера для изменения (рабочий режим, тип волны, режим связи ) // ----------------------------------------------- -------------------------------------------------- ---------------------------------- if (encoderSpin) {if (encoderSpin ==CW &&idy <2) idy ++; если (encoderSpin ==CCW &&idy> 0) idy--; selectIcon (idy, БЕЛЫЙ); } // ----------------------------------------------- -------------------------------------------------- ---------------------------------- // ОПЦИИ режима:переключатель энкодера в относительный режим // --- -------------------------------------------------- -------------------------------------------------- ---------------------------- если (encoderPush) {encoderPush =false; // selectIcon (idy, ЧЕРНЫЙ); selectOption (idy); hideCursor (0); idy =варианты [idy]; } ломать; // конечный режим ОПЦИИ case OPTMODE:// 4 // ------------------------------------- -------------------------------------------------- -------------------------------------------- // режим OPTMODE:Encoder иконки режима выбора вращения (логарифмический, однозначный, развертка) // ------------------------------------- -------------------------------------------------- -------------------------------------------- if (encoderSpin) {если (encoderSpin ==CW &&idy <2) idy ++; если (encoderSpin ==CCW &&idy> 0) idy--; selectIcon (idy, БЕЛЫЙ); } // ----------------------------------------------- -------------------------------------------------- ---------------------------------- // режим OPTMODE:Encoder push выберите рабочий режим для установки (хранится в опции [ 0]) // --------------------------------------------- -------------------------------------------------- ------------------------------------ если (encoderPush) {encoderPush =false; байт pMode =_WorkMode; переключатель (idy) {case 0:hideCursor (0); drawSymbol (0); lFreq =lLastFreq; displayFrequency (lFreq); _setWorkMode (ЛОГАРИФМИЧЕСКИЙ); ломать; случай 1:drawSymbol (0); selectDigit (0); lFreq =lLastFreq; displayFrequency (lFreq); _setWorkMode (ОДИН ЦИФРА); ломать; случай 2:lLastFreq =lFreq; displayFrequency (_SweepMin); // готов к запуску _setWorkMode (SWEEP); ломать; } mode =_WorkMode; если (pMode! =_WorkMode) saveConfig (); если (_CouplingMode ==OFF) resetCouplingMode (); idx =0; drawAllIcons (); } ломать; // конечный режим OPTMODE case OPTWAVE:// 5 // ------------------------------------- -------------------------------------------------- ------------------------- // режим OPTWAVE:вращение энкодера перемещает курсор влево и вправо для выбора волны (sqr, sin, tri) // - -------------------------------------------------- -------------------------------------------------- ----------- if (encoderSpin) {если (encoderSpin ==CW &&idy <2) idy ++; если (encoderSpin ==CCW &&idy> 0) idy--; selectIcon (idy, БЕЛЫЙ); } // ----------------------------------------------- -------------------------------------------------- ------------------- // режим OPTWAVE:Encoder push устанавливает новый тип волны // ------------------ -------------------------------------------------- ------------------------------------------------ если ( encoderPush) {encoderPush =false; если (_WaveType! =idy) {_setWaveType (idy); saveConfig (); } Частота обновления(); // обновляет волновой тип drawAllIcons (); idx =0; mode =_WorkMode; } ломать; // конечный режим OPTWAVE case OPTCOUP:// 6 // ------------------------------------- -------------------------------------------------- ------------------------- // режим OPTCOUP:вращение энкодера перемещает курсор влево и вправо для выбора режима связи // ------- -------------------------------------------------- -------------------------------------------------- ----- if (encoderSpin) {если (encoderSpin ==CW &&idy <2) idy ++; если (encoderSpin ==CCW &&idy> 0) idy--; selectIcon (idy, БЕЛЫЙ); } // ----------------------------------------------- -------------------------------------------------- ------------------- // mode OPTCOUP:Encoder push выбрать текущий режим связи // ------------------ -------------------------------------------------- ------------------------------------------------ если ( encoderPush) {encoderPush =false; setCouplingMode (idy); drawAllIcons (); idx =0; mode =_WorkMode; } ломать; // конечный режим OPTCOUP case OPTSWEEP:// 7 // ------------------------------------- -------------------------------------------------- ----------------------------- // режим OPTSWEEP:Encoder spin выберите значения развертки для редактирования // ------- -------------------------------------------------- -------------------------------------------------- --------- if (encoderSpin) {if (encoderSpin ==CW &&idy <2) idy ++; // указатель увеличения по часовой стрелке if (encoderSpin ==CCW &&idy> 0) idy--; // указатель уменьшения против часовой стрелки selectIcon (idy, WHITE); // выбираем первую иконку displayFrequency (_Sweep (idy)); // отображаем текущее значение развертки} if (encoderPush) {encoderPush =false; // ------------------------------------------------ -------------------------------------------------- ------------------ // режим OPTSWEEP:энкодер нажмите, подтвердите значения развертки для редактирования // ------------------ -------------------------------------------------- ------------------------------------------------ drawSymbol ( 0); selectDigit (0); selectIcon (idy, БЕЛЫЙ); idx =0; displayFrequency (_Sweep (idy)); mode =SWEEPEDIT; } ломать; // конечный режим OPTSWEEP case SWEEPEDIT:// 8 // ------------------------------------- -------------------------------------------------- ----------------------- // режим SWEEPEDIT:вращение энкодера выберите цифру для изменения // -------------- -------------------------------------------------- ---------------------------------------------- if (encoderSpin) {если (encoderSpin ==CW &&idx  0) idx--; // указатель уменьшения против часовой стрелки selectDigit (idx); } // ----------------------------------------------- -------------------------------------------------- ------------- // режим SWEEPEDIT:долгое нажатие кодировщика выход из режима редактирования и возврат в SWEEP // --------------------- -------------------------------------------------- --------------------------------------- if (encoderLongPush ==LONGPUSH) {encoderPush =false; drawAllIcons (); displayFrequency (_SweepMin); hideCursor (idx); _setWorkMode (SWEEP); SweepReset (); mode =_WorkMode; задержка (250); } если (encoderPush) {encoderPush =false; // ------------------------------------------------ -------------------------------------------------- ----------- // режим SWEEPEDIT:нажатие энкодера перейти в режим DIGITCHANGE // -------------------------- -------------------------------------------------- --------------------------------- hideCursor (idx); // задержка мигания курсора (250); // для selectDigit (idx); // визуальное подтверждение drawSymbol (2); // рисовать значок поворота mode =DIGITCHANGE; // изменить режим} break; // завершить режим SWEEPEDIT case DIGITCHANGE:// 9 // ------------------------------ -------------------------------------------------- ------------------------- // режим DIGITCHANGE:долгое нажатие кодировщика выходит из режима DIGITCHANGE в режиме SWEEP // --------- -------------------------------------------------- ---------------------------------------------- if (encoderLongPush ==LONGPUSH &&_WorkMode ==SWEEP) {encoderPush =false; hideCursor (idx); drawSymbol (1); режим =OPTSWEEP; задержка (250); } // ----------------------------------------------- -------------------------------------------------- -------- // режим DIGITCHANGE:вращение энкодера меняет значение цифры (0 -> 9 -> 0 и так далее) // ------------------ -------------------------------------------------- ------------------------------------- if (encoderSpin) {// вращение энкодера if (encoderSpin ==CW) {// направление по часовой стрелке Freq [idx] ++; если (Freq [idx]> '9') Freq [idx] ='0'; } else {// направление против часовой стрелки Freq [idx] -; if (Freq [idx] <'0') Freq [idx] ='9'; } updateDigit (idx, Freq [idx]); // обновить цифру на дисплее} // ----------------------------------------- -------------------------------------------------- -------------- // режим DIGITCHANGE:возврат энкодера в режим SINGLEDIGIT или SWEEPEDIT // --------------------- -------------------------------------------------- ---------------------------------- if (encoderPush) {// флаг отправки кодировщика установлен прерыванием encoderPush =false; // сбросить флаг события hideCursor (idx); // задержка мигания курсора (250); // для selectDigit (idx); // визуальное подтверждение drawSymbol (0); если (_WorkMode ==SWEEP) {длинный ltemp =_Sweep (idy); // сохраняем значение _setSweep (idy, atol (Freq)); // преобразовываем новое значение из массива в длинное if (_SweepMax> 0 &&_SweepMax> _SweepMin &&_SweepStep>
 0) {// проверяем соответствие нового значения развертки if (_Sweep (idy)! =ltemp) saveConfig (); // если значение изменилось, записываем новое значение в EEPROM displayFrequency (_Sweep (idy)); mode =SWEEPEDIT; // изменить режим} else {_displayErrMsg; // отображаем сообщение об ошибке, сохраненное во флэш-памяти delay (1000); _setSweep (idy, ltemp); // восстанавливаем сохраненное значение displayFrequency (_Sweep (idy)); // повторно отображаем значение drawSymbol (2); // перерисовываем значок поворота}} else {// если не в режиме развертки if (_CouplingMode ==OFF) {// если режим связи, если ВЫКЛ lLastFreq =atol (Freq); // сохраняем текущую частоту resetCouplingMode (); // устанавливаем режим связи по умолчанию} UpdateFrequency (); // отправляем частоту в модуль DDS mode =SINGLEDIGIT; // изменить режим}} break; // режим завершения DIGITCHANGE default:break; }} // ---------------------------------------------- -------------------------------------------------- ----------------------------------- // Нажать событие кодировщика - Вызывается прерыванием // ---- -------------------------------------------------- -------------------------------------------------- --------------------------- void encoderSwitch (void) {encoderPush =true;} // ---------- -------------------------------------------------- -------------------------------------------------- --------------------- // Служебные функции // ----------------------- -------------------------------------------------- -------------------------------------------------- -------- // Рисуем графический интерфейс // ----------------------------------- -------------------------------------------------- --------------------------- void drawInterface () {display.clearDisplay (); display.display (); задержка (1000); display.drawRoundRect (0, 0, 128, 64, 3, БЕЛЫЙ); // рисуем внешний фрейм display.fillRect (1, 1, 126, 14, БЕЛЫЙ); // рисуем рамку подписи displayText (12, 4, strFromFlash (0), ЧЕРНЫЙ, БЕЛЫЙ, МАЛЕНЬКИЙ); // вывод заголовка заголовка delay (1000); if (cTime ==1) {// только при включении питания на displayText (XPOS - 6, YPOS + 10, strFromFlash (1), БЕЛЫЙ, ЧЕРНЫЙ, БОЛЬШОЙ); //show Welcom message delay(1000); display.fillRect(2, 16, display.width() - 3, 35, BLACK); //clear Welcome message cTime =0; } display.display(); displayText(XPOS + 84, YPOS + 4, strFromFlash(2), WHITE, BLACK, SMALL); //print "Hz" sprintf(Freq, "%06li", lFreq); //put frequency value into char array with template "000000" for (int i =MAXDIGIT - 1; i>=0; i--) { display.drawChar(XPOS + 2 + i * DELTAX, YPOS, Freq[i] , WHITE, BLACK, BIG); //Display with animation effect from right to left display.display(); }}//end drawInterface()//----------------------------------------------------------------------------------------------------------------// Print string in x,y pos with specified colors and size//----------------------------------------------------------------------------------------------------------------void displayText(byte x, byte y, const char *str, byte foreColor, byte backColor, byte textSize) { display.setTextSize(textSize); //textsize:SMALL or BIG global const display.setTextColor(foreColor, backColor); //colors WHITE or BLACK global const of the library display.setCursor(x, y); //set the cursor position display.print(str); //str is the pointer to the string of chars display.display(); //update display}//----------------------------------------------------------------------------------------------------------------// Copies element [i] of the string_table array from flash memory to the ram buffer and returns the pointer to the buffer//----------------------------------------------------------------------------------------------------------------char* strFromFlash(byte i) { strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); return (char*)buffer;}//----------------------------------------------------------------------------------------------------------------// Draw or clear a border around selected icon after clearing border of the previous one//----------------------------------------------------------------------------------------------------------------void selectIcon(byte icon, byte color) { static byte prevIcon; display.drawRect(XPOS - 10 + prevIcon * 32, YPOS + 19, 29, 20, BLACK); display.drawRect(XPOS - 10 + icon * 32, YPOS + 19, 29, 20, color); display.display(); prevIcon =icon;}//----------------------------------------------------------------------------------------------------------------// Display all workmode icons//----------------------------------------------------------------------------------------------------------------void displayWorkModeIcons(void) { byte const *bitmap[3] ={imgLog, imgDigit, imgSweep}; _clearIconsArea; for (byte i =0; i <=2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display();}//----------------------------------------------------------------------------------------------------------------// Display all wavetype icons//----------------------------------------------------------------------------------------------------------------void displayWaveTypeIcons(void) { byte const *bitmap[3] ={imgSqr, imgSin, imgTri}; _clearIconsArea; for (byte i =0; i <=2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display();}//----------------------------------------------------------------------------------------------------------------// Display all coupling mode icons//----------------------------------------------------------------------------------------------------------------void displayCouplingModeIcons(void) { byte const *bitmap[3] ={imgCoAc, imgCoDc, imgCoOff}; _clearIconsArea; for (byte i =0; i <=2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display();}//----------------------------------------------------------------------------------------------------------------// Display all sweep icons//----------------------------------------------------------------------------------------------------------------void displaySweepIcons(void) { byte const *bitmap[3] ={imgSwMax, imgSwMin, imgSwStep}; _clearIconsArea; for (byte i =0; i <=2; i++) { display.drawBitmap(XPOS - 8 + i * 32, YPOS + 21, bitmap[i], 25, 16, WHITE); } display.display();}//----------------------------------------------------------------------------------------------------------------// Draw all icons//----------------------------------------------------------------------------------------------------------------void drawAllIcons(void) { _clearIconsArea; drawModeIcon(); if (_WorkMode ==SWEEP || _WorkMode ==SWEEPEDIT ) { display.drawBitmap(XPOS + 24, YPOS + 21, imgSwOpt, 25, 16, WHITE); display.drawBitmap(XPOS + 56, YPOS + 21, imgSwStart, 25, 16, WHITE); drawSymbol(1); idy =2; selectIcon(idy, WHITE); //ready to sweep drawSmallWaveIcon(); drawSmallCouplingIcon(); } else { drawWaveIcon(); drawCouplingIcon(); drawSymbol(0); if (_WorkMode ==SINGLEDIGIT) selectDigit(0); } display.display();}//----------------------------------------------------------------------------------------------------------------// Draws the icon based on the value of relative option//----------------------------------------------------------------------------------------------------------------void drawModeIcon(void) { byte x =XPOS - 8, y =YPOS + 21; byte const *bitmap[3] ={imgLog, imgDigit, imgSweep}; display.fillRect(x, y, 25, 16, BLACK); display.drawBitmap(x, y, bitmap[_WorkMode], 25, 16, WHITE); display.display();}void drawWaveIcon(void) { byte x =XPOS + 24, y =YPOS + 21; const byte *bitmap[3] ={imgSqr, imgSin, imgTri}; display.fillRect(x, y, 25, 16, BLACK); display.drawBitmap(x, y, bitmap[_WaveType], 25, 16, WHITE); display.display(); drawSmallWaveIcon();}void drawCouplingIcon(void) { byte x =XPOS + 56, y =YPOS + 21; const byte *bitmap[3] ={imgCoAc, imgCoDc, imgCoOff}; display.fillRect(x, y, 25, 16, BLACK); display.drawBitmap(x, y, bitmap[_CouplingMode], 25, 16, WHITE); display.display(); drawSmallCouplingIcon();}//----------------------------------------------------------------------------------------------------------------// Draws small wave icon based on the value of relative option//----------------------------------------------------------------------------------------------------------------void drawSmallWaveIcon(void) { byte x =114, y =41; const byte *bitmap[3] ={imgSqrSmall, imgSinSmall, imgTriSmall}; display.fillRect(x, y, 9, 8, BLACK); display.drawBitmap(x, y, bitmap[_WaveType], 9, 8, WHITE); display.display();}//----------------------------------------------------------------------------------------------------------------// Draws small coupling icon based on the value of relative option//----------------------------------------------------------------------------------------------------------------void drawSmallCouplingIcon(void) { byte x =114, y =50; const byte *bitmap[3] ={imgAcSmall, imgDcSmall, imgOffSmall}; display.fillRect(x, y, 9, 8, BLACK); display.drawBitmap(x, y, bitmap[_CouplingMode], 9, 8, WHITE); display.display();}//----------------------------------------------------------------------------------------------------------------// Show cursor at x position//----------------------------------------------------------------------------------------------------------------void showCursor(byte x) { display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, WHITE, WHITE, BIG); display.display();}//----------------------------------------------------------------------------------------------------------------// Hide cursor at x position//----------------------------------------------------------------------------------------------------------------void hideCursor(byte x) { display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, BLACK, BLACK, BIG); display.display();}//----------------------------------------------------------------------------------------------------------------// Show cursor at x position after hiding previous one//----------------------------------------------------------------------------------------------------------------void selectDigit(byte x) { static byte lastDigit; hideCursor(lastDigit); display.drawChar(XPOS + 2 + x * DELTAX, YPOS + DELTAY, CURSOR, WHITE, WHITE, BIG); display.display(); lastDigit =x;}//----------------------------------------------------------------------------------------------------------------// Update single digit frequency to chr value//----------------------------------------------------------------------------------------------------------------void updateDigit(byte digit, char chr) { display.drawChar(XPOS + 2 + digit * DELTAX, YPOS, chr , WHITE, BLACK, BIG); display.display();}//----------------------------------------------------------------------------------------------------------------// Drwaw or clear some symbols/icons//----------------------------------------------------------------------------------------------------------------void drawSymbol(byte symbol) { switch (symbol) { case 0://Top arrow display.fillRect(2, 20, 25, 16, BLACK); display.fillRect(2, 43, 14, 16, BLACK); display.drawChar(XPOS - 20 , YPOS + 4, ARROW, WHITE, BLACK, SMALL); //draw top arrow top break; case 1://Bottom arrow display.fillRect(2, 20, 25, 16, BLACK); display.fillRect(2, 43, 14, 16, BLACK); display.drawChar(XPOS - 20 , YPOS + 25, ARROW, WHITE, BLACK, SMALL); //draw bottom arrow break; case 2://Turn icon display.fillRect(2, 20, 25, 16, BLACK); display.drawBitmap(XPOS - 21, YPOS + 1, imgTurn, 13, 13, WHITE); //draw turn icon break; case 3://Play icons display.fillRect(4, 23, 23, 11, BLACK); //clear pause icon display.drawBitmap(4, 23, imgSwRun, 23, 11, WHITE); //draw sweep icon display.fillRect(XPOS + 56, YPOS + 21, 25, 16, BLACK); //clear icon area display.drawBitmap(XPOS + 56, YPOS + 21, imgSwPause, 25, 16, WHITE); //drwaw sweep play symbol icon break; case 4://Pause icons display.fillRect(4, 23, 23, 11, BLACK); //clear sweep icon display.drawBitmap(4, 23, imgSwPsd, 23, 11, WHITE); //draw pause icon display.fillRect(XPOS + 56, YPOS + 21, 25, 16, BLACK); //clear icon area display.drawBitmap(XPOS + 56, YPOS + 21, imgSwStart, 25, 16, WHITE); //draw sweep pause symbol icon break; case 9://Simply clear symbol area display.fillRect(2, 20, 25, 16, BLACK); //clear top symbol area display.fillRect(2, 43, 14, 16, BLACK); //clear bottom symbol area break; default:break; } display.display();}//---------------------------------------------------------------------------------------------------------------// Set current frequency in DDS module, if frequency is 0 it will be set to 1//---------------------------------------------------------------------------------------------------------------void UpdateFrequency(void) { lFreq =atol(Freq); //convert char array to long if (lFreq <1) { //the frequency at zero makes no sense ++Freq[MAXDIGIT - 1]; //increase the right most digit lFreq =1; //set frequency to 1 } displayFrequency(lFreq); //update the display DDS_FrequencySet(lFreq, Wave[_WaveType]); //send the frequency value to DDS module lLastFreq =lFreq; //save current freq}//---------------------------------------------------------------------------------------------------------------// Display the frequency with the six-zero template//---------------------------------------------------------------------------------------------------------------void displayFrequency(long f) { sprintf(Freq, "%06li", f); //convert long to char with template '000000' displayText(XPOS + 2, YPOS, Freq , WHITE, BLACK, BIG); //print frequency on display display.display(); //refresh display}//---------------------------------------------------------------------------------------------------------------// Reset coupling mode to default//---------------------------------------------------------------------------------------------------------------void resetCouplingMode(void) { if (lFreq ==0 &&_CouplingMode ==OFF) { setCouplingMode(AC); drawCouplingIcon(); }}//---------------------------------------------------------------------------------------------------------------// Set a specific coupling mode//---------------------------------------------------------------------------------------------------------------void setCouplingMode(byte cMode) { byte pMode =_CouplingMode; switch (cMode) { case 0:if (lLastFreq> 0) lFreq =lLastFreq; digitalWrite(PinCoupling, LOW); _setCouplingMode(AC); ломать; case 1:if (lLastFreq> 0) lFreq =lLastFreq; digitalWrite(PinCoupling, HIGH); _setCouplingMode(DC); ломать; case 2:lLastFreq =lFreq; lFreq =0; digitalWrite(PinCoupling, LOW); _setCouplingMode(OFF); ломать; } DDS_FrequencySet(lFreq, Wave[_WaveType]); displayFrequency(lFreq); if (cMode !=pMode) saveConfig();}//---------------------------------------------------------------------------------------------------------------// Select options//---------------------------------------------------------------------------------------------------------------void selectOption(byte opt) { selectIcon(opt, BLACK); switch (opt) { case 0://workMode; displayWorkModeIcons(); selectIcon(_WorkMode, WHITE); mode =OPTMODE; ломать; case 1://waveType; displayWaveTypeIcons(); selectIcon(_WaveType, WHITE); mode =OPTWAVE; ломать; case 2://couplingMode; displayCouplingModeIcons(); selectIcon(_CouplingMode, WHITE); mode =OPTCOUP; ломать; }}//----------------------------------------------------------------------------------------------------------------// Calculate logarithmic steps of the frequency//----------------------------------------------------------------------------------------------------------------long AutoStep(long value, byte spin) { if (spin ==CW) { if (value>=100000) return 100000; if (value>=10000) return 10000; if (value>=1000) return 1000; if (value>=100) return 100; if (value>=10) return 10; if (value>=1) return 1; return 0; // Invalid value } else { if (value <=10) return 1; if (value <=100) return 10; if (value <=1000) return 100; if (value <=10000) return 1000; if (value <=100000) return 10000; if (value <=1000000) return 100000; return 0; // Invalid value }}//-------------------------------------------------------------------------------------------// Start Sweep or restart it from where it came from before the pause//-------------------------------------------------------------------------------------------void FrequencySweep() { do { if (sweepDnPausedVal ==0) { //if sweepDown has not been stopped if (sweepUpPausedVal> 0) { //and sweepUp has been stopped sweepUpPausedVal =SweepUp(sweepUpPausedVal); //continues from current value } else { sweepUpPausedVal =SweepUp(_SweepMin); //else start from min } } if (sweepStatus !=BREAK) { //if sweep has been stopped if (sweepDnPausedVal> 0) { //and sweepDn has been stopped sweepDnPausedVal =SweepDn(sweepDnPausedVal); //continues from current value } else { sweepDnPausedVal =SweepDn(_SweepMax); //else start from max } } } while (sweepStatus !=BREAK); //continues sweep until stopped}//-----------------------------------------------------------------------------------------// Sweep Up from sweepmin push encoder to pause//-----------------------------------------------------------------------------------------long SweepUp(long sweepmin) { long f; for (f =sweepmin; f <_SweepMax; f +=_SweepStep) { DDS_FrequencySet(f, Wave[_WaveType]); displayFrequency(f); if (encoderPush) { sweepStatus =BREAK; ломать; } } if (sweepStatus ==BREAK) return f; return 0;}//-----------------------------------------------------------------------------------------// Sweep down from sweepmax push encoder to pause//-----------------------------------------------------------------------------------------long SweepDn(long sweepmax) { long f; for (f =sweepmax; f> _SweepMin; f -=_SweepStep) { DDS_FrequencySet(f, Wave[_WaveType]); displayFrequency(f); if (encoderPush) { sweepStatus =BREAK; ломать; } } if (sweepStatus ==BREAK)return f; return 0;}//-----------------------------------------------------------------------------------------// Clear global sweep vars and restore display//-----------------------------------------------------------------------------------------void SweepReset(void) { sweepStatus =STILL; sweepUpPausedVal =0; sweepDnPausedVal =0; display.fillRect(4, 23, 23, 11, BLACK); //clear sweep text display.display();}//-----------------------------------------------------------------------------------------// Flash sweep pause icon//-----------------------------------------------------------------------------------------void flashIcon(int interval) { static long previousMillis; static boolean picShow; if (millis() - previousMillis>=interval) { previousMillis =millis(); picShow =!picShow; if (picShow) { display.drawBitmap(4, 23, imgSwPsd, 23, 11, WHITE); //drwaw sweep pause icon display.display(); } else { display.fillRect(4, 23, 23, 11, BLACK); //clear sweep pause icon display.display(); } }}//-----------------------------------------------------------------------------------------// Arduino software reset//-----------------------------------------------------------------------------------------void reset(void) { display.fillRect(1, 16, 125, 46, BLACK); display.display(); displayText(30, 30, strFromFlash(4), WHITE, BLACK, BIG); char str[2]; for (byte i =3; i> 0; i--) { sprintf(str, "%d", i); displayText(95, 30, str, WHITE, BLACK, BIG);...This file has been truncated, please download it to see its full contents.
JXWG_Defs.hC/C++
Declarections section
// This file is an integral part of the JX_WaveGenerator.ino and must be// distributed together with the main file to allow it to function correctly.// The same license of the main file applies to this file.// Janux 01/04/2021 on Turin, Italy.#ifndef JXWG_Defs#define JXWG_Defs#include #include //Encoder library, see https://www.arduino.cc/reference/en/libraries/simplerotary/#include  // //adaptation of the library for SSD1306 to the SH1106 display, see https://github.com/wonho-maker/Adafruit_SH1106#include #define DEBUG 0#define OLED_RESET -1Adafruit_SH1106 display(OLED_RESET);#define PinA 5 //Encoder pin A#define PinB 4 //Encoder pin B #define PinS 3 //Encoder pin SwitchSimpleRotary Encoder(PinA, PinB, PinS);//list of loop mode#define LOGARITHMIC 0 //+workmode#define SINGLEDIGIT 1 //+workmode#define SWEEP 2 //+workmode#define OPTIONS 3 //-submode of LOGARITHMIC and SINGLEDIGIT#define OPTMODE 4 //-submode of OPTIONS#define OPTWAVE 5 //-submode of OPTIONS#define OPTCOUP 6 //-submode of OPTIONS#define OPTSWEEP 7 //-submode of SWEEP#define SWEEPEDIT 8 //-submode of OPTSWEEP#define DIGITCHANGE 9 //-submode of SINGLEDIGIT and SWEEPEDIT#define PinCoupling 7 //Coupling mode pin (relay pin)//constants #define XPOS 28#define YPOS 21#define DELTAX 12#define DELTAY 4#define SMALL 1#define BIG 2#define CW 1#define CCW 2#define PUSH 1#define LONGPUSH 1//Num Freq digit#define MAXDIGIT 6//Wave type#define SQUARE 0#define SINE 1#define TRIANGLE 2//Coupling mode#define AC 0#define DC 1#define OFF 2//Sweep status#define STILL 0#define BREAK 1#define PAUSE 2//Symbols chars#define CURSOR 0x5F#define ARROW 0x10//AD9833 module Pin connection#define DDS_FSY 9#define DDS_CLK 10#define DDS_DAT 11//AD9833 Wave Type const#define wSquare 0x28#define wSine 0x00#define wTriangle 0x02//-----------------------------------------------------------------------------// Variables declarections //-----------------------------------------------------------------------------//Strings constants placed in flash memory save ram spaceconst char str1[] PROGMEM ="JX WAVE GENERATOR"; // 18 byteconst char str2[] PROGMEM ="WELCOME"; // 8 byteconst char str3[] PROGMEM ="Hz"; // 3 byteconst char str4[] PROGMEM ="ERROR!"; // 7 byteconst char str5[] PROGMEM ="RESET"; // 6 byte //42 byte totalconst char* const string_table[] PROGMEM ={str1, str2, str3, str4, str5};char buffer[18]; //local buffer for string, make sure this is large enough for the largest string it must holdlong lFreq =1000; //main frequency variablelong lLastFreq =1000; //used to save the current freq value in some situationslong sweepUpPausedVal =0; //value of sweep when pusedlong sweepDnPausedVal =0; //value of sweep when pusedlong lSweep[3] ={20000, 0, 100}; //Sweep Hz default value MAX, MIN, STEP;byte sweepStatus =STILL; //current status of the sweep processconst byte Wave[] ={wSquare, wSine, wTriangle}; //array for WaveTypevolatile boolean encoderPush =false; //var used in the routine called by interruptchar Freq[MAXDIGIT + 1]; //array for display frequency in 6 digit template "000000"byte mode =0; //current loop modebyte idx =0; //pointer to digit index (0 to 5)byte idy =0; //same of idx in submodelong cTime =1; //screensaver counter//default startup preferencesbyte options[3] ={LOGARITHMIC, SINE, DC}; //mode, wavetype, couplingmode//define others macros#define _WorkMode options[0]#define _setWorkMode(x) options[0]=x#define _WaveType options[1]#define _setWaveType(x) options[1]=x#define _CouplingMode options[2]#define _setCouplingMode(x) options[2]=x#define _reservedbyte 0xFF#define _SweepMax lSweep[0]#define _SweepMin lSweep[1]#define _SweepStep lSweep[2]#define _Sweep(x) lSweep[x]#define _setSweep(x,f) lSweep[x]=f#define _setSweepMax(x) lSweep[0]=x#define _setSweepMin(x) lSweep[1]=x#define _setSweepStep(x) lSweep[2]=x//define short functions macros#define _clearIconsArea display.fillRect(XPOS - 11, YPOS + 18, 94, 24, BLACK)#define _displayErrMsg displayText(XPOS + 2, YPOS, strFromFlash(3), WHITE, BLACK, BIG);//define CONFIG consts &vars #define CONFIG_START 32 //EEPROM Memory start location#define CONFIG_VERSION "JXWG1" //Config version ID//define custom type structtypedef struct { char version[6]; byte workmode; byte wavetype; byte couplingmode; byte reservedbyte; long sweepmax; long sweepmin; long sweepstep;} config_type;//create new struct and load it with default valueconfig_type CONFIG ={ CONFIG_VERSION, _WorkMode, _WaveType, _CouplingMode, _reservedbyte, _SweepMax, _SweepMin, _SweepStep,};//define processor reset functionvoid(*ATmegaReset)(void) =0;#endif
JXWG_Graphics.hC/C++
Icon resource data file
// This file is an integral part of the JX_WaveGenerator.ino and must be// distributed together with the main file to allow it to function correctly.// The same license of the main file applies to this file.// Janux 01/04/2021 on Turin, Italy.#ifndef JXWG_Graphics#define JXWG_Graphics//----------------------------------------------------------------------------------------------// Plain b&w bitmaps PROGMEM icons data//----------------------------------------------------------------------------------------------const byte imgLog[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x88, 0x00, 0x40, 0x80, 0x9c, 0x00, 0x40, 0x80, 0x88, 0x00, 0x80, 0x80, 0x88, 0x00, 0x80, 0x80, 0x88, 0x01, 0x00, 0x80, 0x88, 0x02, 0x00, 0x80, 0x88, 0x0c, 0x00, 0x80, 0x88, 0x30, 0x00, 0x80, 0x89, 0xc0, 0x00, 0x80, 0x8e, 0x00, 0x10, 0x80, 0x9f, 0xff, 0xf8, 0x80, 0x88, 0x00, 0x10, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgDigit[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x9c, 0x47, 0x3e, 0x80, 0xa2, 0xc8, 0x82, 0x80, 0xa6, 0x40, 0x84, 0x80, 0xaa, 0x47, 0x0c, 0x80, 0xb2, 0x48, 0x02, 0x80, 0xa2, 0x48, 0x22, 0x80, 0x9c, 0xef, 0x9c, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x3e, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSweep[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x8f, 0xcf, 0x38, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0x88, 0x49, 0x28, 0x80, 0xb8, 0x79, 0xee, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSqr[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0xff, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0xaa, 0xaa, 0xaa, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x82, 0x88, 0xa0, 0x80, 0xff, 0x80, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSin[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x1c, 0x00, 0x80, 0x82, 0x2a, 0x20, 0x80, 0x80, 0x41, 0x00, 0x80, 0x82, 0x49, 0x20, 0x80, 0x80, 0x80, 0x80, 0x80, 0xaa, 0xaa, 0xaa, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc3, 0x08, 0x61, 0x80, 0xc1, 0x00, 0x41, 0x80, 0xa2, 0x08, 0x22, 0x80, 0x9c, 0x00, 0x1c, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgTri[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x82, 0x08, 0x20, 0x80, 0x82, 0x00, 0x20, 0x80, 0x87, 0x08, 0x70, 0x80, 0x85, 0x00, 0x50, 0x80, 0x8a, 0x88, 0xa8, 0x80, 0x88, 0x80, 0x88, 0x80, 0xba, 0xeb, 0xae, 0x80, 0x90, 0x41, 0x04, 0x80, 0xa2, 0x2a, 0x22, 0x80, 0xa0, 0x22, 0x02, 0x80, 0xc2, 0x1c, 0x21, 0x80, 0xc0, 0x14, 0x01, 0x80, 0x82, 0x08, 0x20, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgCoAc[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x9c, 0x70, 0x00, 0x80, 0xa2, 0x88, 0x00, 0x80, 0xa2, 0x80, 0xc0, 0x80, 0xa2, 0x81, 0x24, 0x80, 0xbe, 0x81, 0x24, 0x80, 0xa2, 0x88, 0x18, 0x80, 0xa2, 0x70, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgCoDc[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xbc, 0x70, 0x00, 0x80, 0xa2, 0x88, 0x00, 0x80, 0xa2, 0x81, 0x54, 0x80, 0xa2, 0x80, 0x00, 0x80, 0xa2, 0x81, 0xfc, 0x80, 0xa2, 0x88, 0x00, 0x80, 0xbc, 0x70, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgCoOff[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x9c, 0xf7, 0x80, 0x80, 0xa2, 0x84, 0x22, 0x80, 0xa2, 0x84, 0x14, 0x80, 0xa2, 0xe7, 0x08, 0x80, 0xa2, 0x84, 0x14, 0x80, 0xa2, 0x84, 0x22, 0x80, 0x9c, 0x84, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSwMax[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x81, 0x00, 0x00, 0x80, 0x82, 0x00, 0x00, 0x80, 0x87, 0x01, 0x00, 0x80, 0x82, 0x03, 0x80, 0x80, 0x82, 0x07, 0xc0, 0x80, 0x82, 0x0f, 0xe0, 0x80, 0x82, 0x1f, 0xf0, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSwMin[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x81, 0x00, 0x00, 0x80, 0x82, 0x00, 0x00, 0x80, 0x87, 0x1f, 0xf0, 0x80, 0x82, 0x0f, 0xe0, 0x80, 0x82, 0x07, 0xc0, 0x80, 0x82, 0x03, 0x80, 0x80, 0x82, 0x01, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSwOpt[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x84, 0x08, 0x10, 0x80, 0x88, 0x1c, 0x38, 0x80, 0x9c, 0x3e, 0x10, 0x80, 0x88, 0x00, 0x00, 0x80, 0x88, 0x00, 0x00, 0x80, 0x88, 0x3e, 0x00, 0x80, 0x88, 0x1c, 0x38, 0x80, 0x88, 0x08, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSwStep[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x84, 0x08, 0x04, 0x80, 0x88, 0x0c, 0x08, 0x80, 0x9c, 0x7e, 0x1c, 0x80, 0x88, 0x7f, 0x08, 0x80, 0x88, 0x7e, 0x08, 0x80, 0x88, 0x0c, 0x08, 0x80, 0x88, 0x08, 0x08, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSwStart[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0xc0, 0x00, 0x80, 0x80, 0xf0, 0x00, 0x80, 0x80, 0xfc, 0x00, 0x80, 0x80, 0xff, 0x00, 0x80, 0x80, 0xff, 0xc0, 0x80, 0x80, 0xff, 0xc0, 0x80, 0x80, 0xff, 0x00, 0x80, 0x80, 0xfc, 0x00, 0x80, 0x80, 0xf0, 0x00, 0x80, 0x80, 0xc0, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgSwPause[] PROGMEM ={ 0xff, 0xff, 0xff, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x81, 0xe3, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x80};const byte imgTurn[] PROGMEM ={ 0x0f, 0x80, 0x30, 0x60, 0x47, 0x10, 0x58, 0xd0, 0x90, 0x48, 0x80, 0xe8, 0x90, 0x48, 0xb8, 0x08, 0x90, 0x48, 0x58, 0xd0, 0x47, 0x10, 0x30, 0x60, 0x0f, 0x80};const byte imgSwRun[] PROGMEM ={ 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x9b, 0xa2, 0x22, 0x6b, 0xae, 0xec, 0x7b, 0xae, 0xec, 0x9a, 0xa6, 0x62, 0xea, 0xae, 0xee, 0x6a, 0xae, 0xee, 0x9c, 0x62, 0x2e, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00};const byte imgSwPsd[] PROGMEM ={ 0x00, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x1c, 0xdb, 0x30, 0x6b, 0x5a, 0xd6, 0x6b, 0x5a, 0xf6, 0x18, 0x5b, 0x32, 0x7b, 0x5b, 0xd6, 0x7b, 0x5a, 0xd6, 0x7b, 0x67, 0x30, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00};//Small icons ---------------------------------------------------------------------------------const byte imgSqrSmall[] PROGMEM ={ 0x00, 0x00, 0x3e, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0xe3, 0x80, 0x00, 0x00};const byte imgSinSmall[] PROGMEM ={ 0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x84, 0x80, 0x84, 0x80, 0x03, 0x00, 0x00, 0x00};const byte imgTriSmall[] PROGMEM ={ 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x88, 0x80, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00};const byte imgAcSmall[] PROGMEM ={ 0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x84, 0x80, 0x84, 0x80, 0x03, 0x00, 0x00, 0x00};const byte imgDcSmall[] PROGMEM ={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x80, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00};const byte imgOffSmall[] PROGMEM ={ 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x14, 0x00, 0x08, 0x00, 0x14, 0x00, 0x22, 0x00, 0x00, 0x00};//Total program memory space used by icons data:1148 byte#endif

Схема

Display type updated

Производственный процесс

  1. Захват капель воды с помощью Arduino
  2. Arduino Spybot
  3. FlickMote
  4. Самодельный телевизор B-Gone
  5. Основные часы
  6. Найди меня
  7. Arduino Power
  8. Скейтборд виртуальной реальности «Сделай сам»
  9. Как связать Arduino Mega с GPS-модулем NEO-6M
  10. Tech-TicTacToe