亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

JX 波形发生器

组件和用品

Arduino Nano R3
我还没有尝试过,但大概你可以使用任何 Arduino 模型
× 1
显示 SH1106 I2C Oled 128x64 像素(4 针)
× 1
AD9833 DDS 模块
× 1
带按钮的旋转编码器
有了这个,你需要烙铁
× 1
旋转编码器模块
对于面包板安装这是更好的
× 1
5V 继电器模块(可选)
可选,如果不需要改变AC/DC输出耦合方式。对于面包板安装这个更好
× 1
继电器簧片 5V 500 欧姆
这对于小信号来说是最好的,但需要烙铁。使用 500 欧姆线圈可以直接连接到 Arduino 数字引脚 (10 mA)。
× 1
电容 10 µF
× 1
电容 10 nF
聚酯电容器
× 1
AC-DC 100-220V 至 5V 降压电源模块
可选,用于在未通过 USB 连接时为电路供电
× 1

必要的工具和机器

烙铁(通用)
如果你想在面包板上测试项目,这不是必需的

应用和在线服务

image2cpp
将自定义图标转换为 PROGMEM 的十六进制格式

关于这个项目

很长一段时间我都推迟购买示波器。现在,在购买之后,是时候还拥有一个廉价的信号发生器供业余爱好使用,对于诊断音频电路等必不可少。结合对电子和计算的两种热情,最好的办法是用 Arduino 自己做。

特点

  • 输出频率介于 1 Hz 和 999999 Hz 之间
  • 两种频率变化模式:对数和个位数
  • 三种波形,正弦波,三角波和方波
  • 交流或直流输出耦合
  • 能够在两个预定义的频率值之间连续扫描
  • 仅由单个旋钮控制
  • 集成屏幕保护程序可延长 oled 显示器的使用寿命

注意

快速参考

原型

我使用了一个具有 10A 触点的预组装继电器模块,因为目前我没有微型簧片继电器,当不需要功率继电器时,这将是避免晶体管二极管和电阻器的最佳选择。 Arduino 数字 PIN 可提供最大 40 mA 的电流,因此您不能直接连接带有 120/150 欧姆线圈的机电继电器。

总是非常非常小心 使用市电电压时!

有触电和/或皮肤和眼睛受损的风险。
照顾好你的生活,你只有一个!

代码

  • JX_Wave_Generator_8.7.7.ino
  • JXWG_Defs.h
  • JXWG_Graphics.h
JX_Wave_Generator_8.7.7.inoC/C++
版本 8.7.7。 1/16/2021
/* 版权所有 (c) 2020 Janux 特此授予获得本软件和相关文档文件(“软件”)副本的任何人免费许可,以处理在不受限制的情况下,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本的权利,并允许向其提供软件的人员这样做,但前提是符合以下条件: 上述版权声明和本许可声明应包含在本软件的所有副本或重要部分中。该软件“按原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于适销性、特定用途的适用性和不侵权的保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任承担责任,无论是在合同诉讼、侵权行为或其他方面,由软件或软件的使用或使用或其他原因引起的或与之相关的软件。配置保存加载代码是对挪威创作网站上 Ragnar Ranyen Homb 的文章“How to Load and Save Configurations on an Arduino”的原创思想的发展。*/#include "JXWG_Defs.h"#include "JXWG_Graphics .h"void setup() { //如果您使用的是简单的编码器和 3x10K 上拉电阻,请在 pinMode(PinA, INPUT) 下方应用此设置; pinMode(PinB,输入);引脚模式(引脚,输入); //如果您使用的是没有 3x10K 电阻的简单编码器,请使用下一个树行 //pinMode(PinA, INPUT_PULLUP); //pinMode(PinB, INPUT_PULLUP); //pinMode(PinS, INPUT_PULLUP); //大多数 PCB 焊接编码器已经在引脚 A 和 B 上有上拉电阻器,但没有在开关引脚上 //然后使用下面的设置 //pinMode(PinA, INPUT); //pinMode(PinB, INPUT); //pinMode(PinS, INPUT_PULLUP);数字写入(引脚A,高);数字写入(PinB,高);数字写入(引脚,高); pinMode(PinCoupling,输出); //耦合模式Encoder.setDebounceDelay(5); display.begin(SH1106_SWITCHCAPVCC, 0x3C); //使用I2C addr 0x3C(对于128x64)进行初始化 display.clearDisplay(); //display.setRotation(2); //如果要倒挂显示,请取消注释此行 Wire.begin(); // 作为主设备加入 i2c 总线 TWBR =5; // freq=615kHz period=1.625uS //分配编码器开关推送事件来中断Arduino attachInterrupt(digitalPinToInterrupt(PinS), encoderSwitch, FALLING)的1 Pin 3; DDS_Init(); //初始化DDS模块;设置配置(); //加载配置并设置启动值} //---> 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); if (encoderSpin) { cTime =millis(); } else { if (millis() - cTime> wTime) { ScreenSaver(); } } switch (mode) { case LOGARITHMIC://0 //----------------------------------- -------------------------------------------------- ---------------------------------------------- // 模式对数:编码器旋转变化频率对数步长 1,10,100,1000,10000,100000 Hz //------------------------------ -------------------------------------------------- -------------------------------------------------- - if (encoderSpin) { if (lFreq>=1) { lStep =AutoStep(lFreq, encoderSpin); //计算对数步长 } else if (_CouplingMode ==OFF) { //如果耦合模式设置为OFF resetCouplingMode(); //设置Frequency不为0时的默认耦合方式encoderSpin =0; //跳过第一次自旋 } if (encoderSpin ==CW &&lFreq <=999999 - lStep) { //自旋 CW 增加频率 lFreq +=lStep; } if (encoderSpin ==CCW &&lFreq>=lStep + 1) { //spin CCW 递减频率 lFreq -=lStep; DDS_FrequencySet(lFreq, Wave[_WaveType]); //发送频率值到DDS模块displayFrequency(lFreq); //发送格式化的频率以显示 lLastFreq =lFreq; //保存当前频率 } //------------------------------------------- -------------------------------------------------- --------------------------------------- // 工作模式对数:编码器将开关推到 OPTIONS 模式//------------------------------------------------ -------------------------------------------------- --------------------------------- if (encoderPush) { encoderPush =false; //清除推送标志 drawSymbol(1); //绘制箭头符号 selectIcon(0, WHITE); //在第一个图标 idx =0 周围画一个边框; id =0; //重置指针 var mode =OPTIONS; //转到模式选项 } break; //结束模式LOGARITHMIC case SINGLEDIGIT://1 //------------------------------------- -------------------------------------------------- ---------------------- // submode SINGLEDIGIT:编码器旋转左右移动光标 //-------------- -------------------------------------------------- --------------------------------------------- if (encoderSpin) { if (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;选择选项(idy); idy =选项[idy]; } } } 休息; //结束模式SINGLEDIGIT case SWEEP://2 //--------------------------------- -------------------------------------------------- ------------------------- // 工作模式 SWEEP:编码器旋转左右移动光标进行选项选择 //​​-------- -------------------------------------------------- -------------------------------------------------- ---- if (encoderSpin) { if (encoderSpin ==CW &&idy <2) idy++; if (encoderSpin ==CCW &&idy> 0) idy--;选择图标(idy,白色); } if (encoderPush) { //----------------------------------------- -------------------------------------------------- --------------------------------------- // 工作模式 SWEEP:编码器推送转到 OPTIONS,扫描选项或开始/停止扫描 //---------------------------------------- -------------------------------------------------- ---------------------------------------- 编码器推送 =假; switch (idy) { case 0:lFreq =atol(Freq);选择选项(idy); idy =选项[idy];延迟(100); if (_WorkMode !=2) displayFrequency(lLastFreq);扫描重置();休息;情况 1:lFreq =atol(Freq);绘制符号(9);绘制符号(1); displaySweepIcons();选择图标(0,白色); id =0;显示频率(_Sweep(idy));延迟(100);扫描重置();模式 =OPTSWEEP;休息;情况 2://** 扫描状态:STILL 0(从未开始),1 BREAK,2 PAUSE ** if (sweepStatus ==STILL ||扫描状态 ==PAUSE) { drawSymbol(3); //绘制暂停图标 selectIcon(2, WHITE); //选择图标FrequencySweep(); //运行扫描 } else { //如果暂停 drawSymbol(4); //绘制播放图标sweepStatus =PAUSE; } 休息; if (sweepStatus ==PAUSE) flashIcon(250); //闪烁暂停文本中断; //结束模式 SWEEP case OPTIONS://3 if (encoderLongPush) reset(); //------------------------------------------------ -------------------------------------------------- --------------------------------- // mode OPTIONS:编码器自旋选择选项改变(工作模式,波型,耦合模式) //----------------------------------------------- -------------------------------------------------- ---------------------------------- if (encoderSpin) { if (encoderSpin ==CW &&idy <2) id++; if (encoderSpin ==CCW &&idy> 0) idy--;选择图标(idy,白色); } //---------------------------------------------- -------------------------------------------------- ---------------------------------- // 模式选项:编码器将开关推到相对模式 //--- -------------------------------------------------- -------------------------------------------------- ---------------------------- if (encoderPush) { encoderPush =false; //selectIcon(idy, 黑色);选择选项(idy);隐藏光标(0); idy =选项[idy]; } 休息; //结束模式OPTIONS case OPTMODE://4 //--------------------------------- -------------------------------------------------- -------------------------------------------- // 模式 OPTMODE:编码器旋转选择模式图标(对数、个位数、扫描)//------------------------------------ -------------------------------------------------- -------------------------------------------- if (encoderSpin) { if (encoderSpin ==CW &&idy <2) idy++; if (encoderSpin ==CCW &&idy> 0) idy--;选择图标(idy,白色); } //---------------------------------------------- -------------------------------------------------- ---------------------------------- // mode OPTMODE:编码器推送选择工作模式设置(存储在选项[ 0]) //----------------------------------------- -------------------------------------------------- ------------------------------------- if (encoderPush) { encoderPush =false;字节 pMode =_WorkMode; switch (idy) { case 0:hideCursor(0);绘制符号(0); lFreq =lLastFreq;显示频率(lFreq); _setWorkMode(对数);休息;情况 1:drawSymbol(0);选择数字(0); lFreq =lLastFreq;显示频率(lFreq); _setWorkMode(SINGLEDIGIT);休息;情况 2:lLastFreq =lFreq;显示频率(_SweepMin); //准备开始_setWorkMode(SWEEP);休息; } 模式 =_WorkMode; if (pMode !=_WorkMode) saveConfig(); if (_CouplingMode ==OFF) resetCouplingMode(); idx =0; drawAllIcons(); } 休息; //结束模式 OPTMODE case OPTWAVE://5 //--------------------------------- -------------------------------------------------- ------------------------- // 模式 OPTWAVE:编码器旋转左右移动光标进行波形选择 (sqr, sin, tri) //- -------------------------------------------------- -------------------------------------------------- ----------- if (encoderSpin) { if (encoderSpin ==CW &&idy <2) idy++; if (encoderSpin ==CCW &&idy> 0) idy--;选择图标(idy,白色); } //---------------------------------------------- -------------------------------------------------- ------------------- // 模式 OPTWAVE:编码器推送设置新的波形类型 //----------------- -------------------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - - 如果 (编码器推送){ 编码器推送 =假; if (_WaveType !=idy) { _setWaveType(idy);保存配置();更新频率(); //更新波形 drawAllIcons(); idx =0;模式 =_WorkMode; } 休息; //结束模式OPTWAVE case OPTCOUP://6 //--------------------------------- -------------------------------------------------- ------------------------- // mode OPTCOUP:编码器旋转左右移动光标进行耦合模式选择 //​​------- -------------------------------------------------- -------------------------------------------------- ----- if (encoderSpin) { if (encoderSpin ==CW &&idy <2) idy++; if (encoderSpin ==CCW &&idy> 0) idy--;选择图标(idy,白色); } //---------------------------------------------- -------------------------------------------------- ------------------- // mode OPTCOUP:编码器推送选择当前耦合模式 //----------------- -------------------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - - 如果 (编码器推送){ 编码器推送 =假;设置耦合模式(idy); drawAllIcons(); idx =0;模式 =_WorkMode; } 休息; //结束模式OPTCOUP case OPTSWEEP://7 //------------------------------------ -------------------------------------------------- ----------------------------- // 模式 OPTSWEEP:编码器旋转选择要编辑的扫描值 //------- -------------------------------------------------- -------------------------------------------------- --------- 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模式:编码器推确认扫描值编辑 //----------------- -------------------------------------------------- ------------------------------------------------ 绘制符号( 0);选择数字(0);选择图标(idy,白色); idx =0;显示频率(_Sweep(idy));模式 =SWEEPEDIT; } 休息; //结束模式OPTSWEEP case SWEEPEDIT://8 //--------------------------------- -------------------------------------------------- --------------- // 模式 SWEEPEDIT:编码器旋转选择要更改的数字 //-------------- -------------------------------------------------- ---------------------------------------------- if (encoderSpin) { if (encoderSpin ==CW &&idx  0) idx--; //逆时针递减指针 selectDigit(idx); } //---------------------------------------------- -------------------------------------------------- ------------- // 模式 SWEEPEDIT:编码器 longpush 退出编辑并返回 SWEEP //-------------------- -------------------------------------------------- --------------------------------------- if (encoderLongPush ==LONGPUSH) { encoderPush =false; drawAllIcons();显示频率(_SweepMin);隐藏光标(idx); _setWorkMode(SWEEP);扫描重置();模式 =_WorkMode;延迟(250); } if (encoderPush) { encoderPush =false; //------------------------------------------------ -------------------------------------------------- ----------- // 模式 SWEEPEDIT:编码器推动进入模式 DIGITCHANGE //------------------------- -------------------------------------------------- --------------------------------- hideCursor(idx); //闪烁光标延迟(250); //对于selectDigit(idx); //视觉确认 drawSymbol(2); //绘制转弯图标 mode =DIGITCHANGE; //改变模式 } break;//结束模式 SWEEPEDIT case DIGITCHANGE://9 //------------------------------ -------------------------------------------------- ------------------------- // DIGITCHANGE 模式:SWEEP 模式下编码器 longpush 退出 DIGITCHANGE //--------- -------------------------------------------------- ---------------------------------------------- if (encoderLongPush ==LONGPASH &&_WorkMode ==SWEEP) { encoderPush =false;隐藏光标(idx);绘制符号(1);模式 =OPTSWEEP;延迟(250); } //---------------------------------------------- -------------------------------------------------- -------- // mode DIGITCHANGE:编码器旋转改变数字值(0 -> 9 -> 0 等等) //----------------- -------------------------------------------------- ------------------------------------- if (encoderSpin) { //编码器旋转 if (encoderSpin ==CW) { //顺时针方向 Freq[idx]++;如果(频率[idx]> '9')频率[idx] ='0'; } else { //逆时针方向Freq[idx]--;如果(频率[idx] <'0')频率[idx] ='9'; } updateDigit(idx, Freq[idx]); //更新显示的数字 } //---------------------------------------- -------------------------------------------------- -------------- // DIGITCHANGE 模式:编码器按下返回模式 SINGLEDIGIT 或 SWEEPEDIT //-------------------- -------------------------------------------------- ---------------------------------- if (encoderPush) { //由中断设置的编码器推送标志 encoderPush =false; //重置事件标志 hideCursor(idx); //闪烁光标延迟(250); //对于selectDigit(idx); //视觉确认 drawSymbol(0); if (_WorkMode ==SWEEP) { long ltemp =_Sweep(idy); //保存值 _setSweep(idy, atol(Freq)); //将数组中的新值转换为long if (_SweepMax> 0 &&_SweepMax> _SweepMin &&_SweepStep>
 0) { //检查新扫描值的一致性 if (_Sweep(idy) !=ltemp) saveConfig(); //如果值已更改,则在 EEPROM 中写入新值 displayFrequency(_Sweep(idy));模式 =SWEEPEDIT; //改变模式 } else { _displayErrMsg; //显示存储在闪存中的错误信息 delay(1000); _setSweep(idy, ltemp); //恢复保存的值 displayFrequency(_Sweep(idy)); //重新显示值 drawSymbol(2); //重绘转弯图标 } } else { //如果不在扫描模式 if (_CouplingMode ==OFF) { //如果耦合模式 if OFF lLastFreq =atol(Freq); //保存当前频率 resetCouplingMode(); //设置默认耦合模式 } UpdateFrequency(); //发送频率到DDS模块模式=SINGLEDIGIT; //改变模式 } } break; //结束模式DIGITCHANGE默认值:break; }}//---------------------------------------------- -------------------------------------------------- -----------------------------------// 推送编码器事件 - 被中断调用 //---- -------------------------------------------------- -------------------------------------------------- ---------------------------void encoderSwitch(void) { encoderPush =true;}//--------- -------------------------------------------------- -------------------------------------------------- ---------------------// 实用函数//------------------------ -------------------------------------------------- -------------------------------------------------- --------// 绘制图形界面//----------------------------------- -------------------------------------------------- ---------------------------void drawInterface() { display.clearDisplay(); display.display();延迟(1000); display.drawRoundRect(0, 0, 128, 64, 3, WHITE); //draw external frame display.fillRect(1, 1, 126, 14, WHITE); //draw caption frame displayText(12, 4, strFromFlash(0), BLACK, WHITE, SMALL); //print caption title delay(1000); if (cTime ==1) { //only on power on displayText(XPOS - 6, YPOS + 10, strFromFlash(1), WHITE, BLACK, BIG); //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;返回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;返回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. DIY 虚拟现实滑板
  9. 如何将 Arduino Mega 与 NEO-6M GPS 模块连接
  10. Tech-TicTacToe
  11. Arduino Quadruped
  12. u-blox LEA-6H 02 GPS 模块,带有 Arduino 和 Python